package com.xhui.vimarket.common.utils.vo;

import java.util.Collections;
import java.util.List;

import org.apache.commons.lang.StringUtils;

/**
 * 与具体ORM实现无关的分页参数及查询结果封装 注意所有序号从1开始.
 * 
 * @版权：福富软件 版权所有 (c) 2010
 * @文件：com.xhui.crm.common.vo.Page.java
 * @所含类：Page Page中记录的类型
 * @author: peilh
 * @version: V1.0
 * @see:
 * @创建日期：Feb 25, 2010
 * @功能说明：
 * @修改记录： =============================================================<br>
 *        日期:Feb 25, 2010 peilh 创建
 *        =============================================================<br>
 * @param <T>
 */
public class Page<T> {
    /**
     * 升序.
     */
    public static final String ASC        = "asc";
    /**
     * 降序.
     */
    public static final String DESC       = "desc";
    /**
     * 分页参数.
     */
    protected int              pageNo     = 1;
    /**
     * 页面记录数.
     */
    protected int              pageSize   = 1;
    /**
     * 排序字段.
     */
    protected String           orderBy    = null;
    /**
     * 排序.
     */
    protected String           order      = null;
    /**
     * 自动另外执行。
     */
    protected boolean          autoCount  = true;
    
    /**
     * 返回结果.
     */
    protected List<T>          result     = Collections.emptyList();
    /**
     * 总记录数.
     */
    protected long             totalCount = -1;
   
    /**
     * 构造函数.
     */
    public Page() {
    }
    /**
     * 构造函数.
     * @param pageSize 记录数
     */
    public Page(final int pageSize) {
        this.pageSize = pageSize;
    }
    
    /**
     * 获得当前页的页号,序号从1开始,默认为1.
     * 
     * @return 当前页的页号
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public int getPageNo() {
        return this.pageNo;
    }
    
    /**
     * 设置当前页的页号,序号从1开始,低于1时自动调整为1.
     * 
     * @param pageNo 页号
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public void setPageNo(final int pageNo) {
        this.pageNo = pageNo;
        
        if (pageNo < 1) {
            this.pageNo = 1;
        }
    }
    
    /**
     * @param thePageNo 前页的页号
     * @return Page
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public Page<T> pageNo(final int thePageNo) {
        this.setPageNo(thePageNo);
        return this;
    }
    
    /**
     * 获得每页的记录数量,默认为1.
     * 
     * @return 每页的记录数量
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public int getPageSize() {
        return this.pageSize;
    }
    
    /**
     * 设置每页的记录数量,低于1时自动调整为1.
     * 
     * @param pageSize 每页的记录数量
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public void setPageSize(final int pageSize) {
        this.pageSize = pageSize;
        
        if (pageSize < 1) {
            this.pageSize = 1;
        }
    }
    /**
     * .
     * @param thePageSize 每页的记录数量
     * @return Page
     */
    public Page<T> pageSize(final int thePageSize) {
        this.setPageSize(thePageSize);
        return this;
    }
    
    /**
     * 根据pageNo和pageSize计算当前页第一条记录在总结果集中的位置,序号从1开始.
     * 
     * @return 位置
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public int getFirst() {
        return ((this.pageNo - 1) * this.pageSize) + 1;
    }
    
    /**
     * 获得排序字段,无默认值.多个排序字段时用','分隔.
     * 
     * @return orderBy
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public String getOrderBy() {
        return this.orderBy;
    }
    
    /**
     * @param orderBy 排序字段
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public void setOrderBy(final String orderBy) {
        this.orderBy = orderBy;
    }
    /**
     * 排序.
     * @param theOrderBy  排序字段
     * @return Page
     */
    public Page<T> orderBy(final String theOrderBy) {
        this.setOrderBy(theOrderBy);
        return this;
    }
    
    /**
     * 获得排序方向.
     * 
     * @return order
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public String getOrder() {
        return this.order;
    }
    
    /**
     * 设置排序方式向.
     * 
     * @param order
     *            可选值为desc或asc,多个排序字段时用','分隔.
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public void setOrder(final String order) {
        // 检查order字符串的合法值
        final String[] orders = StringUtils.split(StringUtils.lowerCase(order),
            ',');
        for (final String orderStr : orders) {
            if (!StringUtils.equals(Page.DESC, orderStr)
                && !StringUtils.equals(Page.ASC, orderStr)) {
                throw new IllegalArgumentException("排序方向" + orderStr + "不是合法值");
            }
        }
        
        this.order = StringUtils.lowerCase(order);
    }
    /**
     * 获取排序方式向.
     * @param theOrder 排序方式向
     * @return Page
     */
    public Page<T> order(final String theOrder) {
        this.setOrder(theOrder);
        return this;
    }
    
    /**
     * 是否已设置排序字段,无默认值.
     * 
     * @return true or false
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public boolean isOrderBySetted() {
        return (StringUtils.isNotBlank(this.orderBy) && StringUtils
            .isNotBlank(this.order));
    }
    
    /**
     * 查询对象时是否自动另外执行count查询获取总记录数, 默认为false.
     * 
     * @return true or false
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public boolean isAutoCount() {
        return this.autoCount;
    }
    
    /**
     * 查询对象时是否自动另外执行count查询获取总记录数.
     * 
     * @param autoCount 记录数
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public void setAutoCount(final boolean autoCount) {
        this.autoCount = autoCount;
    }
    /**
     * 设置自动另外执行count查询获取总记录数.
     * @param theAutoCount 记录数
     * @return Page
     */
    public Page<T> autoCount(final boolean theAutoCount) {
        this.setAutoCount(theAutoCount);
        return this;
    }
    
    /**
     * 取得页内的记录列表.
     *  
     * @return 记录列表
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public List<T> getResult() {
        return this.result;
    }
    
    /**
     * 设置页内的记录列表.
     * 
     * @param result 结果集
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public void setResult(final List<T> result) {
        this.result = result;
    }
    
    /**
     * 取得总记录数, 默认值为-1.
     * 
     * @return 总记录数
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public long getTotalCount() {
        return this.totalCount;
    }
    
    /**
     * 设置总记录数.
     * 
     * @param totalCount 总记录数
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public void setTotalCount(final long totalCount) {
        this.totalCount = totalCount;
    }
    
    /**
     * 根据pageSize与totalCount计算总页数, 默认值为-1.
     * 
     * @return 总页数
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public long getTotalPages() {
        if (this.totalCount < 0) {
            return -1;
        }
        
        long count = this.totalCount / this.pageSize;
        if (this.totalCount % this.pageSize > 0) {
            count++;
        }
        return count;
    }
    
    /**
     * 是否还有下一页.
     * 
     * @return true or false
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public boolean isHasNext() {
        return (this.pageNo + 1 <= this.getTotalPages());
    }
    
    /**
     * 取得下页的页号, 序号从1开始. 当前页为尾页时仍返回尾页序号.
     * 
     * @return 下页的页号
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public int getNextPage() {
        if (this.isHasNext()) {
            return this.pageNo + 1;
        } else {
            return this.pageNo;
        }
    }
    
    /**
     * 是否还有上一页.
     * 
     * @return true or false
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public boolean isHasPre() {
        return (this.pageNo - 1 >= 1);
    }
    
    /**
     * 取得上页的页号, 序号从1开始. 当前页为首页时返回首页序号.
     * 
     * @return 上页的页号
     * @author: peilh
     * @修改记录： ==============================================================<br>
     *        日期:Feb 25, 2010 peilh 创建方法，并实现其功能
     *        ==============================================================<br>
     */
    public int getPrePage() {
        if (this.isHasPre()) {
            return this.pageNo - 1;
        } else {
            return this.pageNo;
        }
    }
}
